package com.lineage.server.datatables;

import com.add.L1Config_other;
import com.lineage.DatabaseFactory;
import com.lineage.server.model.Instance.L1CrockInstance;
import com.lineage.server.model.Instance.L1PcInstance;
import com.lineage.server.model.L1Location;
import com.lineage.server.model.L1Teleport;
import com.lineage.server.serverpackets.S_BlueMessage;
import com.lineage.server.serverpackets.S_ServerMessage;
import com.lineage.server.serverpackets.ServerBasePacket;
import com.lineage.server.thread.GeneralThreadPool;
import com.lineage.server.utils.L1SpawnUtil;
import com.lineage.server.utils.SQLUtil;
import com.lineage.server.world.World;
import com.lineage.server.world.WorldCrock;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Collection;
import java.util.Iterator;
import java.util.Random;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class ServerCrockTable {
  private static final Log _log = LogFactory.getLog(ServerCrockTable.class);
  
  private static boolean STATUS = false;
  
  private static boolean STATUS_KILLBOSS = false;
  
  private static Timestamp _start_time = null;
  
  private static Timestamp _end_time = null;
  
  private static Timestamp _kill_time = null;
  
  private static final int _teleport_time = 150;
  
  private static int _MAP_TYPE = 0;
  
  private static int[] _THEBES_MAPID = new int[] { 780, 781, 782 };
  
  private static int[] _TIKAL_MAPID = new int[] { 783, 784 };
  
  private static int[][] _CROCK_MAPIDS = new int[][] { _THEBES_MAPID, _TIKAL_MAPID };
  
  private boolean _isTeleport;
  
  private static final int[][] CROCK_LOC = new int[][] { { 32728, 32709, 4 }, { 32848, 32639, 4 }, { 32852, 32705, 4 }, { 32913, 33168, 4 }, { 32913, 33425, 4 }, { 32957, 33247, 4 }, { 34232, 33312, 4 }, { 34255, 33203, 4 }, { 34276, 33359, 4 } };
  
  private static L1Location CROCK_LOC_OPEN = null;
  
  private static final Random _random = new Random();
  
  private static ServerCrockTable _instance;
  
  public static ServerCrockTable get() {
    if (_instance == null)
      _instance = new ServerCrockTable(); 
    return _instance;
  }
  
  private ServerCrockTable() {
    this._isTeleport = false;
    load();
  }
  
  private void load() {
    long time = System.currentTimeMillis();
    Timestamp nowtime = new Timestamp(time);
    Connection con = null;
    PreparedStatement pstm = null;
    ResultSet rs = null;
    try {
      con = DatabaseFactory.get().getConnection();
      pstm = con.prepareStatement("SELECT * FROM `server_crock`");
      rs = pstm.executeQuery();
      while (rs.next()) {
        _start_time = rs.getTimestamp("start_time");
        _end_time = rs.getTimestamp("end_time");
        int open_type = rs.getInt("open_type");
        if (open_type >= 0)
          _MAP_TYPE = open_type; 
        _kill_time = rs.getTimestamp("kill_time");
        int kill_type = rs.getInt("kill_type");
        if (_start_time != null && _start_time.before(nowtime)) {
          addStartTime(true);
          break;
        } 
        if (_kill_time != null) {
          if (!_kill_time.before(nowtime))
            continue; 
          updateKillTime(null);
          _kill_time = null;
          long l = _start_time.getTime() - time;
          open_crock open_crock = new open_crock(l);
          open_crock.start();
          continue;
        } 
        long starttime = _start_time.getTime() - time;
        open_crock open = new open_crock(starttime);
        open.start();
      } 
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(rs);
      SQLUtil.close(pstm);
      SQLUtil.close(con);
    } 
    if (_start_time == null) {
      addStartTime(false);
      _log
        .info("载入时空裂痕开启/结束:" + _start_time + "/" + _end_time);
    } 
  }
  
  private void addStartTime(boolean update) {
    Calendar start = Calendar.getInstance();
    if (start.get(11) >= 19)
      start.add(5, 1); 
    start.set(11, 19);
    start.set(12, 0);
    start.set(13, 0);
    Timestamp start_time = new Timestamp(start.getTimeInMillis());
    Calendar end = Calendar.getInstance();
    if (start.get(11) >= 19)
      end.add(5, 1); 
    end.set(11, 22);
    end.set(12, 0);
    end.set(13, 0);
    Timestamp end_time = new Timestamp(end.getTimeInMillis());
    Connection co = null;
    PreparedStatement ps = null;
    try {
      co = DatabaseFactory.get().getConnection();
      if (update) {
        ps = co.prepareStatement(
            "UPDATE `server_crock` SET `start_time`=?,`end_time`=?, `open_type`=?, `kill_time`=?");
      } else {
        ps = co.prepareStatement(
            "INSERT INTO `server_crock` SET `start_time`=?,`end_time`=?, `open_type`=?, `kill_time`=?");
      } 
      ps.setTimestamp(1, start_time);
      ps.setTimestamp(2, end_time);
      ps.setInt(3, 0);
      ps.setTimestamp(4, null);
      ps.execute();
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(ps);
      SQLUtil.close(co);
    } 
    load();
    _log.info("加入时空裂痕时间");
  }
  
  private void updateStartTime() {
    Calendar start = Calendar.getInstance();
    start.add(5, L1Config_other._4046);
    start.set(11, 19);
    start.set(12, 0);
    start.set(13, 0);
    Timestamp start_time = new Timestamp(start.getTimeInMillis());
    Calendar end = Calendar.getInstance();
    end.add(5, L1Config_other._4046);
    end.set(11, 22);
    end.set(12, 0);
    end.set(13, 0);
    Timestamp end_time = new Timestamp(end.getTimeInMillis());
    Connection co = null;
    PreparedStatement ps = null;
    try {
      co = DatabaseFactory.get().getConnection();
      ps = co.prepareStatement(
          "UPDATE `server_crock` SET `start_time`=?, `end_time`=?, `open_type`=?, `kill_time`=?");
      ps.setTimestamp(1, start_time);
      ps.setTimestamp(2, end_time);
      if (_MAP_TYPE == 0) {
        ps.setInt(3, 1);
      } else {
        ps.setInt(3, 0);
      } 
      ps.setTimestamp(4, null);
      ps.execute();
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(ps);
      SQLUtil.close(co);
    } 
    _log.info("更新时空裂痕时间");
  }
  
  private void updateKillTime(Timestamp kill_time) {
    Connection co = null;
    PreparedStatement ps = null;
    try {
      co = DatabaseFactory.get().getConnection();
      ps = co.prepareStatement("UPDATE `server_crock` SET `kill_time`=?, `kill_type`=?");
      ps.setTimestamp(1, kill_time);
      ps.setInt(2, _MAP_TYPE);
      ps.execute();
    } catch (SQLException e) {
      _log.error(e.getLocalizedMessage(), e);
    } finally {
      SQLUtil.close(ps);
      SQLUtil.close(co);
    } 
  }
  
  public void updateKillTime() {
    if (!STATUS)
      return; 
    STATUS_KILLBOSS = true;
    Timestamp kill_time = new Timestamp(System.currentTimeMillis() + 86400000L);
    updateKillTime(_kill_time = kill_time);
    if (_MAP_TYPE == 0) {
      Message(1474);
      Message(1475);
    } else if (_MAP_TYPE == 1) {
      Message(1488);
      Message(1489);
    } 
  }
  
  public boolean checkTeleport(int locX, int locY, int mapId, L1PcInstance pc) {
    if (STATUS && Math.abs(CROCK_LOC_OPEN.getX() - locX) <= 2 && 
      Math.abs(CROCK_LOC_OPEN.getY() - locY) <= 2 && 
      mapId == CROCK_LOC_OPEN.getMapId()) {
      int[][] locx = { { 32647, 32863, 780 }, { 32817, 32739, 783 } };
      int[] loc = locx[_MAP_TYPE];
      int newX = loc[0];
      int newY = loc[1];
      short newMap = (short)loc[2];
      pc.setSkillEffect(78, 2000);
      pc.stopHpRegeneration();
      pc.stopMpRegeneration();
      L1Teleport.teleport(pc, newX, newY, newMap, pc.getHeading(), false);
      return true;
    } 
    return false;
  }
  
  public void loginMessage(L1PcInstance pc) {
    if (STATUS)
      pc.sendPackets((ServerBasePacket)new S_ServerMessage(1466)); 
  }
  
  public boolean checkBoss() {
    return (!STATUS_KILLBOSS && this._isTeleport);
  }
  
  private void Message(int msg_id) {
    Collection<L1PcInstance> allpc = World.get().getAllPlayers();
    if (allpc.isEmpty())
      return; 
    Iterator<L1PcInstance> iterator = allpc.iterator();
    while (iterator.hasNext()) {
      L1PcInstance pc = iterator.next();
      int mapId = pc.getMapId();
      int array[], length = (array = _CROCK_MAPIDS[_MAP_TYPE]).length;
      int j = 0;
      while (j < length) {
        int i = array[j];
        if (mapId == i)
          pc.sendPackets((ServerBasePacket)new S_ServerMessage(msg_id)); 
        j++;
      } 
    } 
  }
  
  private void teleport() {
    Collection<L1PcInstance> allpc = World.get().getAllPlayers();
    if (allpc.isEmpty())
      return; 
    Iterator<L1PcInstance> iterator = allpc.iterator();
    while (iterator.hasNext()) {
      L1PcInstance pc = iterator.next();
      int mapId = pc.getMapId();
      if (mapId >= 780 && mapId <= 784)
        L1Teleport.teleport(pc, 33973, 33245, (short)4, 4, true); 
    } 
  }
  
  public void kill_boss_teleport() {
    try {
      World.get().broadcastPacketToAll((ServerBasePacket)new S_BlueMessage(1470));
      Thread.sleep(5000L);
      Collection<L1PcInstance> allpc = World.get().getAllPlayers();
      if (allpc.isEmpty())
        return; 
      Iterator<L1PcInstance> iterator = allpc.iterator();
      while (iterator.hasNext()) {
        L1PcInstance pc = iterator.next();
        int mapId = pc.getMapId();
        if (mapId >= 780 && mapId <= 784) {
          World.get().broadcastPacketToAll((ServerBasePacket)new S_BlueMessage(1478));
          Thread.sleep(5000L);
          World.get().broadcastPacketToAll((ServerBasePacket)new S_BlueMessage(1480));
          Thread.sleep(1000L);
          World.get().broadcastPacketToAll((ServerBasePacket)new S_BlueMessage(1481));
          Thread.sleep(1000L);
          World.get().broadcastPacketToAll((ServerBasePacket)new S_BlueMessage(1482));
          Thread.sleep(1000L);
          World.get().broadcastPacketToAll((ServerBasePacket)new S_BlueMessage(1483));
          Thread.sleep(1000L);
          World.get().broadcastPacketToAll((ServerBasePacket)new S_BlueMessage(1484));
          Thread.sleep(1000L);
          L1Teleport.teleport(pc, 33973, 33245, (short)4, 4, true);
        } 
      } 
    } catch (Exception e) {
      _log.error(e.getLocalizedMessage(), e);
    } 
  }
  
  private class open_crock implements Runnable {
    private long _delay;
    
    public open_crock(long delay) {
      this._delay = delay;
    }
    
    private void start() {
      GeneralThreadPool.get().schedule(this, this._delay);
    }
    
    public void run() {
      try {
        ServerCrockTable.this.updateStartTime();
        ServerCrockTable.STATUS = true;
        int[] r = ServerCrockTable.CROCK_LOC[ServerCrockTable._random
            .nextInt(ServerCrockTable.CROCK_LOC.length)];
        L1Location loc = new L1Location(r[0], r[1], r[2]);
        ServerCrockTable.CROCK_LOC_OPEN = loc;
        ServerCrockTable._log.info("时空裂痕开启座标:" + r[0] + "," + r[1]);
        L1CrockInstance crock = L1SpawnUtil.spawn(loc);
        if (crock != null) {
          World.get().broadcastPacketToAll((ServerBasePacket)new S_ServerMessage(1469));
          if (ServerCrockTable._end_time != null) {
            long time = System.currentTimeMillis();
            long endtime = ServerCrockTable._end_time.getTime() - time;
            ServerCrockTable.close_crock close = new ServerCrockTable.close_crock(endtime);
            close.start();
          } 
          long teleporttime = 9000000L;
          ServerCrockTable.open_bossRoom teleport = new ServerCrockTable.open_bossRoom(9000000L);
          teleport.start();
        } 
      } catch (Exception e) {
        ServerCrockTable._log.error(e.getLocalizedMessage(), e);
      } 
    }
  }
  
  private class close_crock implements Runnable {
    private long _delay;
    
    public close_crock(long delay) {
      this._delay = delay;
    }
    
    private void start() {
      GeneralThreadPool.get().schedule(this, this._delay);
    }
    
    public void run() {
      try {
        if (ServerCrockTable._kill_time == null) {
          World.get().broadcastPacketToAll((ServerBasePacket)new S_ServerMessage(1467));
          Thread.sleep(2000L);
          ServerCrockTable.this.Message(1478);
          Thread.sleep(4000L);
          if (!ServerCrockTable.STATUS_KILLBOSS) {
            if (ServerCrockTable._MAP_TYPE == 0) {
              ServerCrockTable.this.Message(1479);
            } else if (ServerCrockTable._MAP_TYPE == 1) {
              ServerCrockTable.this.Message(1490);
            } 
          } else {
            ServerCrockTable.this.updateKillTime(null);
          } 
          Thread.sleep(1000L);
          ServerCrockTable.this.Message(1480);
          Thread.sleep(1000L);
          ServerCrockTable.this.Message(1481);
          Thread.sleep(1000L);
          ServerCrockTable.this.Message(1482);
          Thread.sleep(1000L);
          ServerCrockTable.this.Message(1483);
          Thread.sleep(1000L);
          ServerCrockTable.this.Message(1484);
          Thread.sleep(1000L);
          ServerCrockTable.this.teleport();
          Thread.sleep(1500L);
          Collection<L1CrockInstance> allCrock = WorldCrock.get().all();
          if (allCrock.isEmpty())
            return; 
          Iterator<L1CrockInstance> iter = allCrock.iterator();
          while (iter.hasNext()) {
            L1CrockInstance crock = iter.next();
            crock.deleteMe();
          } 
          World.get().broadcastPacketToAll((ServerBasePacket)new S_ServerMessage(1468));
          ServerCrockTable.STATUS = false;
        } 
        ServerCrockTable.this._isTeleport = false;
      } catch (Exception e) {
        ServerCrockTable._log.error(e.getLocalizedMessage(), e);
      } 
    }
  }
  
  private class open_bossRoom implements Runnable {
    private long _delay;
    
    public open_bossRoom(long delay) {
      this._delay = delay;
    }
    
    private void start() {
      GeneralThreadPool.get().schedule(this, this._delay);
    }
    
    public void run() {
      try {
        ServerCrockTable.this._isTeleport = true;
      } catch (Exception e) {
        ServerCrockTable._log.error(e.getLocalizedMessage(), e);
      } 
    }
  }
}
